<template>
    <div class="scroll-number">
        <ul ref="numberContainer" :data-json="JSON.stringify(numArr)">
            <!-- 横向数字列表 -->
            <li v-for="(item, index) in numArr.filter(i=>isNum(i.num))" :key="index">
                <div v-if="isNum(item.num)" class="num-box">
                    <div class="num-container" :style="{
                        transition: 'all 1.5s ease-in-out 0s',
                        top: `-${item.top}px`
                    }">
                        <!-- 纵向数字列表 -->
                        <span v-for="(num, idx) in numList" :key="idx">
                            {{ num }}
                        </span>
                    </div>
                </div>
                <!-- 非数字直接展示 -->
                <div v-else class="num-box">
                    <div class="num-container">
                        <span class="not-num">{{ item.num }}</span>
                    </div>
                </div>
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    name: 'ScrollNumber',
    props: {
        number: {
            type: [Number, String],
            default: 0
        },
        thousands: {
            type: Boolean,
            default: true
        }
    },
    data() {
        return {
            numArr: [],
            numList: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        };
    },
    watch: {
        number: {
            handler() {
                this.scroll()
            },
            deep: true
        }
    },
    mounted() {
        this.$nextTick(() => {
            this.scroll()
        })
    },
    methods: {
        isNum(val) {
            const nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
            return nums.includes(val)
        },
        scroll() {
            const numStr = this.thousands ? this.number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : this.number.toString()
            let oldNums = this.numArr;
            let numArrs = numStr.split('');
            let cNum = numArrs.length - oldNums.length;
            numArrs = numArrs.map((value, index) => {
                let obj = {
                    num: value,
                    top: 0
                };
                if (oldNums.length != 0) {
                    if (index - cNum >= 0) {
                        obj['top'] = oldNums[index - cNum]['top'];
                    }
                }
                return obj;
            })
            this.numArr = numArrs;
            // 获取一个数字展示的高度
            let height = parseFloat(this.$refs.numberContainer.getBoundingClientRect().height)
            this.numArr.forEach((val, index) => {
                if (this.isNum(val.num)) {
                    setTimeout(() => {
                        val.top = parseFloat(val.num * height);
                    }, 10)
                }
            });
        }
    }
};
</script>

<style lang="less" scoped>
.scroll-number {
    text-align: center;

    ul {
        display: inline-block;
        height: 26px;
        text-align: center;

        li {
            float: left;
            width: 18px;
            height: 26px;
            text-align: center;
            margin: 0;
            list-style: none;

            .num-box {
                position: relative;
                width: 100%;
                height: 100%;
                overflow: hidden;

                .num-container {
                    position: absolute;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;

                    .not-num {
                        position: absolute;
                        right: 0;
                        top: 0;
                        width: 100%;
                        height: 100%;
                        line-height: 26px;
                    }

                    span {
                        width: 100%;
                        height: 100%;
                        line-height: 26px;
                        float: left;
                        text-align: center;
                        font-size: 20px;
                        font-weight: 600;
                        color: #2CDF8B;
                    }
                }
            }
        }
    }
}
</style>